<?php

namespace App\V3\V3_2_7\Services;

use App\Services\CommonService;
use App\Services\MessageService;
use App\V3\V3_2_7\Models\LogInStorageModel;
use App\V3\V3_2_7\Models\LogOutStorageModel;
use App\V3\V3_2_7\Models\MaterielTypeModel;
use App\V3\V3_2_7\Models\SerialNumberModel;
use App\V3\V3_2_7\Models\StorageBatchModel;
use App\V3\V3_2_7\Models\StorageManageModel;
use App\V3\V3_2_7\Models\StorageModel;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ScanCodeAllotService
{
    /**
     *扫码调拨
     * Author: zlf
     * Created at 2024/5/28 14:13
     * @param $data
     * @return void
     */
    public static function scanCodeAllot($data)
    {
        //出库仓库信息
        $outStorageInfo = StorageModel::query()
            ->select(
                'a.id as out_storage_id',
                'b.id as out_shelf_id',
                'c.id as out_location_id',
                'storage_name',
                'shelf_name',
                'location_name',
                'storage_address',
            )->from('storage as a')
            ->leftJoin('storage_shelf as b','b.storage_id','=','a.id')
            ->leftJoin('storage_shelf_location as c','c.shelf_id','=','b.id')
            ->where([
                'a.id' => $data['out_storage_id'],
                'b.id' => $data['out_shelf_id'],
                'c.id' => $data['out_location_id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
                'b.status' => 1,
                'c.status' => 1
            ])->first();

        if(empty($outStorageInfo))
            return ['code'=>1,'msg'=>'出库仓库信息，不存在！','data'=>''];
        //入库仓库信息
        $inStorageInfo = StorageModel::query()
            ->select(
            'a.id as in_storage_id',
            'b.id as in_shelf_id',
            'c.id as in_location_id',
            'storage_name',
            'shelf_name',
            'location_name',
            'storage_address',
            )->from('storage as a')
            ->leftJoin('storage_shelf as b','b.storage_id','=','a.id')
            ->leftJoin('storage_shelf_location as c','c.shelf_id','=','b.id')
            ->where([
                'a.id' => $data['in_storage_id'],
                'b.id' => $data['in_shelf_id'],
                'c.id' => $data['in_location_id'],
                'a.main_id' => $data['main_id'],
                'a.delete_flag' => 0,
                'b.status' => 1,
                'c.status' => 1
            ])->first();

        if(empty($inStorageInfo))
            return ['code'=>1,'msg'=>'入库仓库信息，不存在！','data'=>''];
        $goodsInfo = "";
        DB::beginTransaction();
        try {
            switch ($data['code_type']){
                case 0://商品码
                    if(strpos($data['batch_no'], 'smycg') !== false) {
                        $condition['a.id'] = substr($data['batch_no'],5,strlen($data['batch_no'])-1);
                    }else{
                        throw new \Exception('未找到相关商品');
                    }
                case 3://条形码
                //case 4://库存码
                    if($data['code_type'] == 3){
                        if(strpos($data['batch_no'],'SMYCYJ') !== false){
                            $condition['inventory_code'] = explode('SMYCYJ',$data['batch_no'])[1];
                        }else{
                            $condition['bar_code'] = $data['batch_no'];
                        }
                    }
                $goodsInfo = MaterielTypeModel::query()
                    ->select(
                        'a.*',
                        'a.id as type_id',
                        'b.id as materiel_class_id',
                        'b.class_name',
                        'b.class_no',
                        'c.id as first_class',
                    )->from('materiel_type as a')
                        ->leftJoin('materiel_class as b', 'b.id', '=', 'a.materiel_class_id')
                        ->leftJoin('materiel_class as c', 'c.id', '=', 'b.parent_id')
                        ->where([
                        'a.delete_flag' =>0,
                        'a.main_id' => $data['main_id']
                    ])->where($condition)->first();
                break;
                case 1://序列码
                $goodsInfo = SerialNumberModel::query()
                    ->select(
                        'b.*',
                        'b.id as type_id',
                        'a.id as serial_id',
                        'c.id as materiel_class_id',
                        'c.class_name',
                        'c.class_no',
                        'd.id as first_class',
                        'a.status'
                    )->from('serial_number as a')
                    ->leftJoin('materiel_type as b','b.id','=','a.goods_id')
                    ->leftJoin('materiel_class as c', 'c.id', '=', 'b.materiel_class_id')
                    ->leftJoin('materiel_class as d', 'd.id', '=', 'c.parent_id')
                    ->where([
                        'a.delete_flag' => 0,
                        'b.delete_flag' => 0,
                        'serial_no' => $data['batch_no'],
                        'a.main_id' => $data['main_id'],
                    ])->where(function($query)use($data){
                        if(!empty($data['goods_id'])){
                            $query->where('a.goods_id',$data['goods_id']);
                        }
                    })->first();
                if(!empty($goodsInfo)){
                    if($goodsInfo['status'] == 0){
                        throw new \Exception('序列号（'.$data['batch_no'].'）已出库,无法使用！');
                    }
                }
                break;
                case 2://批次码
                $goodsInfo = StorageBatchModel::query()
                    ->select(
                        'c.*',
                        'c.id as type_id',
                        'a.id as batch_id',
                        'd.id as materiel_class_id',
                        'd.class_name',
                        'd.class_no',
                        'e.id as first_class',
                        'a.batch_left_num'
                    )->from('storage_batch as a')
                    ->leftJoin('storage_manage as b','b.id','=','a.storage_manage_id')
                    ->leftJoin('materiel_type as c','c.id','=','b.type_id')
                    ->leftJoin('materiel_class as d', 'd.id', '=', 'c.materiel_class_id')
                    ->leftJoin('materiel_class as e', 'e.id', '=', 'd.parent_id')
                    ->where([
                        'a.delete_flag' => 0,
                        'b.delete_flag' => 0,
                        'c.delete_flag' => 0,
                        'batch_no' => $data['batch_no'],
                        'a.main_id' => $data['main_id'],
                    ])->first();
                    if(!empty($goodsInfo)){
                        if($goodsInfo['batch_left_num'] <= 0){
                            throw new \Exception('批次号（'.$data['batch_no'].'）数量不足！');
                        }
                    }
                break;
            }
            if(empty($goodsInfo))
                throw new \Exception('未找到相关商品');
            if(!empty($goodsInfo['is_use_serial'])){
                throw new \Exception("您开启了序列号，请选择序列号调拨！");
            }
            $data['allocate_no'] = CommonService::getOrderNo(
                new LogOutStorageModel,
                'allocate_no',
                'A'
            );
            SELF::allotOutStorage($goodsInfo,$outStorageInfo,$data);//出库操作
            SELF::allotInStorage($goodsInfo,$inStorageInfo,$data);//入库操作
            DB::commit();
            return ['code' =>0,'msg'=>'success','data'=>''];
        }catch (\Exception $e){
            DB::rollBack();
            Log::debug('扫码调拨异常：'.var_export($e->getMessage(),true));
            return ['code' =>1,'msg'=>$e->getMessage(),'data'=>''];
        }
    }

    /**
     *扫码调拨-出库操作
     * Author: zlf
     * Created at 2024/5/29 9:39
     * @param $goodsInfo
     * @param $outStorageInfo
     * @param $data
     * @return void
     * @throws \Exception
     */
    private static function allotOutStorage($goodsInfo,$outStorageInfo,$data)
    {
        $storageManageInfo = StorageManageModel::query()
        ->select('a.*')
        ->from('storage_manage as a')
        ->leftJoin('materiel_type as b','b.id','=','a.type_id')
        ->leftJoin('storage as c','c.id','=','a.storage_id')
        ->leftJoin('storage_shelf as d','d.id','=','a.shelf_id')
        ->leftJoin('storage_shelf_location as e','e.id','=','a.location_id')
        ->where([
            'a.delete_flag' => 0,
            'type_id' => $goodsInfo['type_id'],
            'a.storage_id' => $data['out_storage_id'],
            'a.shelf_id' => $data['out_shelf_id'],
            'location_id' => $data['out_location_id']
        ])->first();

        if(empty($storageManageInfo)) throw new \Exception('未找到相关，商品库存信息！');
        if($storageManageInfo['in_storage_num'] <= 0){
            throw new \Exception('商品数量不足');
        }
        if($data['code_type'] == 2){
            $storageBatchInfo = StorageBatchModel::query()
               ->where([
               'delete_flag' => 0,
               'main_id' => $data['main_id'],
               'id' => $$data['batch_no'],
            ])->first();
        }else {
            $storageBatchInfo = StorageBatchModel::query()->where([
               'delete_flag' => 0,
               'main_id' => $data['main_id'],
               'storage_manage_id' => $storageManageInfo['id'],
            ])->first();
        }

        if(!empty($storageBatchInfo)){
            $batchId = $storageBatchInfo->id;
            $batchNo = $storageBatchInfo->batch_no;
            $storageBatchInfo->batch_left_num -= 1;
            $storageBatchInfo->save();
        }else{
            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            do{
                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            }
            while(!empty(StorageBatchModel::where('batch_no', $batchNo)->first()));
            $batchId = StorageBatchModel::query()
                ->insertGetId([
                'batch_no' => $batchNo,
                'storage_manage_id' => $storageManageInfo['id'],
                'batch_num' => 1,
                'batch_left_num' => 0,
                'batch_cost' => $goodsInfo['cost']??0,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => $data['time']
            ]);
        }
        if($data['code_type'] == 1){
            //序列号类型相关处理
            $info = SerialNumberModel::query()
                ->where([
                    'id'=> $goodsInfo['serial_id'],
                    'goods_id' => $goodsInfo['type_id'],
                    'main_id'  => $data['main_id'],
                ])->first();
            if(empty($info))
                throw new \Exception('序列号（'.$data['batch_no'].'），不存在');
            $info->delete_flag = 1;
            $info->status = 0;
            $info->save();
        }
        LogOutStorageModel::query()
        ->insertGetId([
            'type' => 11,
            'batch_no' => $batchNo,
            'storage_batch_id' => $batchId,
            'storage_id' => $outStorageInfo['out_storage_id'],
            'storage_name' => $outStorageInfo['storage_name'],
            'storage_address' => $outStorageInfo['storage_address'],
            'curr_storage_manage_id' => $storageManageInfo['id'],
            'materiel_class_id' => $goodsInfo['materiel_class_id'],
            'materiel_class_name' => $goodsInfo['class_name'],
            'materiel_class_no' => $goodsInfo['class_no'],
            'materiel_type_id' => $goodsInfo['type_id'],
            'materiel_name' => $goodsInfo['materiel_name'],
            'type_name' => $goodsInfo['type_name'],
            'materiel_no' => $goodsInfo['materiel_no'],
            'operate_num' => 1,
            'last_storage_num' => $storageManageInfo['in_storage_num'],
            'next_storage_num' => $storageManageInfo['in_storage_num'] - 1,
            'sell_price' => $goodsInfo['selling_price'],
            'materiel_mean_cost' => $storageManageInfo['materiel_mean_cost'],
            'user_id' => $data['user_id'],
            'main_id' => $data['main_id'],
            'all_id_type' => 8,
            'allocate_no' => $data['allocate_no'],
            'shelf_id' => $outStorageInfo['out_shelf_id'],
            'location_id' => $outStorageInfo['out_location_id'],
            'serial_number' => $data['code_type'] == 1 ? $data['batch_no'] : '',
            'out_storage_time' => $data['time'],
            'created_at' => $data['time']
        ]);

        MessageService::sendAlertSms(
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $storageManageInfo['in_storage_num'] - 1,
            $storageManageInfo['alert_num'],
            $data,
            $outStorageInfo['out_storage_id'],
            $outStorageInfo['storage_name'],
            1
        );

        MessageService::sendShortSms(
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $storageManageInfo['in_storage_num'] - 1,
            $data,
            $outStorageInfo['storage_name'],
            $outStorageInfo['out_storage_id'],
        );

        MessageService::sendOutSms(
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $storageManageInfo['in_storage_num'] - 1,
            $outStorageInfo['storage_name'],
            1,
            $data,
            $outStorageInfo['out_storage_id'],
            $storageManageInfo['alert_num']
        );
        StorageManageModel::query()
            ->where([
                'id'=>$storageManageInfo['id']
            ])->decrement('in_storage_num',1);
    }



    /**
     *扫码调拨-入库操作
     * Author: zlf
     * Created at 2024/5/28 16:08
     * @param $goodsInfo
     * @param $data
     * @return void
     */
    private static function allotInStorage($goodsInfo,$inStorageInfo,$data)
    {
        $storageManageInfo = StorageManageModel::query()
            ->select('a.*')
            ->from('storage_manage as a')
            ->leftJoin('materiel_type as b','b.id','=','a.type_id')
            ->leftJoin('storage as c','c.id','=','a.storage_id')
            ->leftJoin('storage_shelf as d','d.id','=','a.shelf_id')
            ->leftJoin('storage_shelf_location as e','e.id','=','a.location_id')
            ->where([
                'type_id' => $goodsInfo['type_id'],
                'a.storage_id' => $data['in_storage_id'],
                'a.shelf_id' => $data['in_shelf_id'],
                'location_id' => $data['in_location_id'],
            ])->first();

        $num = 1;
        if(!empty($storageManageInfo)){
            $manageId = $storageManageInfo['id'];
            StorageManageModel::query()->where([
                'id' => $storageManageInfo['id']
            ])->increment('in_storage_num',1);
            $num += $storageManageInfo['in_storage_num'];
        }else{
            $manageId = StorageManageModel::query()
                ->insertGetId([
                'materiel_class_id' => $goodsInfo['materiel_class_id'],//物料二级分类id
                'materiel_class_name' => $goodsInfo['class_name'],//物料二级分类名称
                'materiel_class_no' => empty($goodsInfo['class_no'])?'':$goodsInfo['class_no'],//物料二级分类名称
                'type_id' => $goodsInfo['type_id'],//物料id
                'materiel_name' => $goodsInfo['materiel_name'],//物料名称
                'type_name' => $goodsInfo['type_name'],//物料型号名称
                'materiel_no' => empty($goodsInfo['materiel_no'])?'':$goodsInfo['materiel_no'],//物料编号
                'materiel_mean_cost' => $goodsInfo['cost']??0,
                'storage_id' => $inStorageInfo['in_storage_id'],//仓库id
                'storage_name' => $inStorageInfo['storage_name'],//仓库名
                'storage_address' => $inStorageInfo['storage_address'],//仓库地址
                'in_storage_num' =>1,//采购单内物料商品入库数量
                'main_id' => $data['main_id'],//主账号id
                'in_storage_time' => $data['time'],//入库时间
                'alert_num' => 0,
                'created_at' => $data['time'],
                'shelf_id' => $inStorageInfo['in_shelf_id'],
                'location_id' => $inStorageInfo['in_location_id']
            ]);

        }
        $storageBatchInfo = StorageBatchModel::query()->where([
            'delete_flag' => 0,
            'main_id' =>$data['main_id'],
            'storage_manage_id' => $manageId,
        ])->first();

        if(!empty($storageBatchInfo)){
            $batchId = $storageBatchInfo->id;
            $batchNo = $storageBatchInfo->batch_no;
            $storageBatchInfo->batch_num += 1;
            $storageBatchInfo->batch_left_num += 1;
            $storageBatchInfo->save();
        }else{
            $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            do{
                $batchNo = $data['batch_title'].date('YmdHis', time()) .mt_rand(1000, 9999).'0';
            }
            while(!empty(StorageBatchModel::where('batch_no', $batchNo)->first()));
            $batchId = StorageBatchModel::query()->insertGetId([
                'batch_no' => $batchNo,
                'storage_manage_id' => $manageId,
                'batch_num' => 1,
                'batch_left_num' => 1,
                'batch_cost' => $goodsInfo['cost']??0,
                'materiel_id' => 0,
                'main_id' => $data['main_id'],
                'created_at' => $data['time']
            ]);
        }

        if($data['code_type'] == 1){
            $info = SerialNumberModel::query()
                ->where([
                    'serial_no'         => $data['batch_no'],
                    'goods_id'          => $goodsInfo['type_id'],
                    'storage_manage_id' => $manageId,
                    'main_id' => $data['main_id'],
                ])->first();
            if(!empty($info))
                throw new \Exception('序列号（'.$data['batch_no'].'）已存在');
            SerialNumberModel::query()
                ->insertGetId([
                'serial_no'         => $data['batch_no'],
                'goods_id'          => $goodsInfo['type_id'],
                'storage_manage_id' => $manageId,
                'created_at'        => $data['time'],
                'main_id' => $data['main_id'],
            ]);
        }
        //入库操作记录
        LogInStorageModel::query()->insert([
            'type' => 9,//日志类型;0:入库;1:调拨入库;2:直接入库;3生产订单还库;4:扫码入库;5:套件返仓;6导入入库;7撤销还库;8退换货入库;9扫码调拨入库
            'storage_id' => $inStorageInfo['in_storage_id'],//入库目标仓库id
            'storage_name' => $inStorageInfo['storage_name'],//仓库名
            'storage_address' => $inStorageInfo['storage_address'],//仓库地址
            'last_storage_id' => $data['out_storage_id'],//调拨前所在仓库id
            'materiel_class_id' => $goodsInfo['materiel_class_id'],//物料二级分类id
            'materiel_class_name' => $goodsInfo['class_name'],//物料二级分类名称
            'materiel_class_no' => empty($goodsInfo['class_no'])?'':$goodsInfo['class_no'],//物料二级分类名称
            'materiel_type_id' => $goodsInfo['type_id'],//物料id
            'materiel_name' => $goodsInfo['materiel_name'],//物料名称
            'type_name' => $goodsInfo['type_name'],//物料型号名称
            'materiel_no' => empty($goodsInfo['materiel_no'])?'':$goodsInfo['materiel_no'],//物料编号
            'operate_num' => 1,//操作数量
            'last_storage_num' => !empty($storageManageInfo)?$storageManageInfo['in_storage_num']:0,//操作前库存数
            'next_storage_num' => $num,//操作后库存数
            'materiel_mean_cost' => $goodsInfo['cost']??0,//物料均价
            'in_storage_time' => $data['time'],//入库时间
            'remark' => "",//备注
            'all_id_type' => 10,//单据类型;0:无;1:报溢;2:退货;3:采购;4:生产订单;6：组件返仓;7导入入库;8撤销还库;9退换货入库;10扫码调拨入库
            'all_id' => 0,//单据id
            'batch_no' => $batchNo,//批次号
            'batch_id' => $batchId,//批次号id
            'user_id' => $data['user_id'],//操作人id
            'main_id' => $data['main_id'],//主账号id
            'created_at' => $data['time'],
            'allocate_no' => $data['allocate_no'],
            'curr_storage_manage_id' => $manageId,
            'serial_number'=>$data['code_type'] == 1 ? $data['batch_no'] : '',
            'shelf_id' => $inStorageInfo['in_shelf_id'],
            'location_id' => $inStorageInfo['in_location_id']
        ]);
        MessageService::sendInSms(
            '无',
            $goodsInfo['materiel_name'],
            $goodsInfo['type_name'],
            $inStorageInfo['in_storage_id'],
            $inStorageInfo['storage_name'],
            $data,
            $inNum = !empty($storageManageInfo)?$storageManageInfo['in_storage_num']:0,
            $num
        );
    }
}
